package de.unikoblenz.west.csxpoi;

import java.io.UnsupportedEncodingException;

/**
 * Encapsulates relations, which comprise a property as the predicate and a
 * category as the object.
 */
public class RelationWrapper {

	/**
	 * the property which is the predicate of the relation
	 */
	private PropertyWrapper mPredicate;

	/**
	 * the category which is the object of the relation
	 */
	private CategoryWrapper mObject;

	/**
	 * whether the relation has been removed
	 */
	private boolean mRemoved = false;

	/**
	 * whether the relation has been imported
	 */
	private boolean mImported = false;

	/**
	 * Creates a (possibly imported) relation with the specified property as the
	 * predicate and the specified category as the object.
	 * 
	 * @param predicate
	 *            the property to be the predicate of the relation
	 * @param object
	 *            the category to be the object of the relation
	 * @param imported
	 *            whether the relation has been imported
	 */
	RelationWrapper(PropertyWrapper predicate, CategoryWrapper object,
			boolean imported) {
		mPredicate = predicate;
		mObject = object;
		mImported = imported;
	}

	/**
	 * Creates a relation with the specified property as the predicate and the
	 * specified category as the object.
	 * 
	 * @param predicate
	 *            the property to be the predicate of the relation
	 * @param object
	 *            the category to be the object of the relation
	 */
	RelationWrapper(PropertyWrapper predicate, CategoryWrapper object) {
		this(predicate, object, false);
	}

	/**
	 * Sets the removed status of the relation.
	 * 
	 * @param removed
	 *            whether the relation has been removed
	 */
	public void setRemoved(boolean removed) {
		mRemoved = removed;
	}

	/**
	 * Gets the propety which is the predicate of the relation.
	 * 
	 * @return the propety which is the predicate of the relation
	 */
	public PropertyWrapper getPredicate() {
		return mPredicate;
	}

	/**
	 * Gets the category which is the object of the relation.
	 * 
	 * @return the category which is the object of the relation
	 */
	public CategoryWrapper getObject() {
		return mObject;
	}

	/**
	 * Tests whether the relation has been removed.
	 * 
	 * @return whether the relation has been removed.
	 */
	public boolean isRemoved() {
		return mRemoved;
	}

	/**
	 * Tests whether the relation has been imported.
	 * 
	 * @return whether the relation has been imported
	 */
	public boolean isImported() {
		return mImported;
	}

	/**
	 * Generates the URL string for the modification REST request representing
	 * the relation.
	 * 
	 * @param categoryUri
	 *            the URI of the category which is the subject
	 * @param userId
	 *            the ID of the issuing user
	 * @return the URL string for the modification REST request representing the
	 *         relation
	 * @throws UnsupportedEncodingException
	 */
	public String generateModificationUrlString(String categoryUri,
			String userId) throws UnsupportedEncodingException {
		String urlString = null;
		if (mImported && mRemoved) {
			if (mPredicate.isInverse()) {
				urlString = Constants.REST_ADDRESS + "categories/"
						+ Encoder.urlEncode(mObject.getUri()) + "?user="
						+ Encoder.urlEncode(userId) + "&deletes="
						+ Encoder.urlEncode(mPredicate.getUri()) + "&value="
						+ Encoder.urlEncode(categoryUri);
			} else {
				urlString = Constants.REST_ADDRESS + "categories/"
						+ Encoder.urlEncode(categoryUri) + "?user="
						+ Encoder.urlEncode(userId) + "&deletes="
						+ Encoder.urlEncode(mPredicate.getUri()) + "&value="
						+ Encoder.urlEncode(mObject.getUri());
			}
		}
		if (!mImported && !mRemoved) {
			if (mPredicate.isInverse()) {
				urlString = Constants.REST_ADDRESS + "categories/"
						+ Encoder.urlEncode(mObject.getUri()) + "?user="
						+ Encoder.urlEncode(userId) + "&adds="
						+ Encoder.urlEncode(mPredicate.getUri()) + "&value="
						+ Encoder.urlEncode(categoryUri);
			} else {
				urlString = Constants.REST_ADDRESS + "categories/"
						+ Encoder.urlEncode(categoryUri) + "?user="
						+ Encoder.urlEncode(userId) + "&adds="
						+ Encoder.urlEncode(mPredicate.getUri()) + "&value="
						+ Encoder.urlEncode(mObject.getUri());
			}
		}
		return urlString;
	}

	/**
	 * Relations are equal if the URIs of the predicates and the URIs of the
	 * objects match.
	 */
	@Override
	public boolean equals(Object object) {
		try {
			RelationWrapper relation = (RelationWrapper) object;
			return mPredicate.equals(relation.getPredicate())
					&& mObject.equals(relation.getObject());
		} catch (ClassCastException e) {
			return false;
		} catch (NullPointerException e) {
			return false;
		}
	}

}